import Map from 'ol/Map';
import View from 'ol/View';
import {get, fromLonLat, toLonLat, transform} from 'ol/proj';
import Feature, {createStyleFunction} from 'ol/Feature';
import {Point, LinearRing, Circle, LineString, Polygon} from 'ol/geom';
import {getTopLeft, getWidth, getCenter} from 'ol/extent';
import {Tile as TileLayer, Vector as VectorLayer, Heatmap as HeatmapLayer, Layer} from 'ol/layer';
import {WMTS as WMTSSource, Vector as VectorSource, XYZ, Cluster} from 'ol/source';
import {Style, Icon, Fill, Stroke, Circle as CircleStyle, Text} from 'ol/style';
import WMTSTileGrid from 'ol/tilegrid/WMTS';
import * as d3 from 'd3';
import rain from './weather-img/rain-avg.png';
import './index.scss';

/**
 * @name: mapArr
 * @desc: 地图配置 1影像 2街道 3地形
 */
const mapArr = [{
    key: '影像',
    name: '卫星图',
    mapType: 1,
    className: 'satellite-map'
}, {
    key: '街道',
    name: '街道图',
    mapType: 2,
    className: 'street-map'
}, {
    key: '地形',
    name: '地形图',
    mapType: 3,
    className: 'terrain-map'
}];

class CanvasLayer extends TileLayer {
    constructor(options) {
        super(options);
        this.features = {
            type: 'FeatureCollection',
            features: [
                {
                    geometry: {
                        type: 'Polygon',
                        id: 53073,
                        coordinates: [options.areaList]
                    },
                    id: 53073,
                    type: 'Feature',
                    properties: {}
                }
            ]
        };

        console.log(this.features);

        d3.select('svg').selectAll('*').remove();
        this.svg = d3
            .select('#main-map')
            .append('svg')
            .style('position', 'absolute');

        // 定义天气特效
        let animateDefs = this.svg.append('defs');
        let pattern = animateDefs.append('pattern')
            .attr('id', 'rain-animate')
            .attr('width', 3104)
            .attr('height', 207)
            .attr('patternUnits', 'userSpaceOnUse');

        pattern.append('image').attr('href', rain)
            .attr('width', 3104)
            .attr('height', 207);

        // 创建 animate 元素
        /*pattern.append('animate')
            .attr('attributeType', 'XML')
            .attr('attributeName', 'x')
            .attr('calcMode', 'discrete')
            .attr('dur', '1s')
            .attr('repeatCount', 'indefinite')
            .attr('values', '0;-206.99999999999997;-413.99999999999994;-620.9999999999999;-827.9999999999999;-1034.9999999999998;-1241.9999999999998;-1448.9999999999998;-1655.9999999999998;-1862.9999999999998;-2069.9999999999995;-2276.9999999999995;-2483.9999999999995;-2690.9999999999995;-2897.9999999999995;');*/

        this.svg.append('path').datum(this.features).attr('class', 'boundary');
        // .attr('fill', `url(#rain-animate)`);
    }

    getSourceState() {
        return 'ready';
    }

    render(frameState) {
        // console.log("frameState")
        // console.log(frameState)
        const width = frameState.size[0];
        const height = frameState.size[1];
        const projection = frameState.viewState.projection;
        // console.log('=======projection:', projection);
        const d3Projection = d3.geoMercator().scale(1)//.translate([0, 0]);
        let d3Path = d3.geoPath().projection(d3Projection);

        const pixelBounds = d3Path.bounds(this.features);
        console.log('=========pixelBounds', pixelBounds);
        const pixelBoundsWidth = pixelBounds[1][0] - pixelBounds[0][0];
        const pixelBoundsHeight = pixelBounds[1][1] - pixelBounds[0][1];

        const geoBounds = d3.geoBounds(this.features);
        const geoBoundsLeftBottom = geoBounds[0];//fromLonLat(geoBounds[0], projection);
        // console.log('=========geoBoundsLeftBottom:', geoBoundsLeftBottom, geoBounds[0]);
        const geoBoundsRightTop = geoBounds[1];//fromLonLat(geoBounds[1], projection);
        let geoBoundsWidth = geoBoundsRightTop[0] - geoBoundsLeftBottom[0];
        if (geoBoundsWidth < 0) {
            geoBoundsWidth += getWidth(projection.getExtent());
        }
        const geoBoundsHeight = geoBoundsRightTop[1] - geoBoundsLeftBottom[1];

        const widthResolution = geoBoundsWidth / pixelBoundsWidth;
        const heightResolution = geoBoundsHeight / pixelBoundsHeight;
        const r = Math.max(widthResolution, heightResolution);
        const scale = r / frameState.viewState.resolution;

        const center = getCenter(frameState.extent);//toLonLat(getCenter(frameState.extent), projection);
        const angle = (-frameState.viewState.rotation * 180) / Math.PI;

        d3Projection
            .scale(scale)
            .center(center)
            .translate([width / 2, height / 2])
            .angle(angle);

        d3Path = d3Path.projection(d3Projection);
        d3Path(this.features);

        this.svg.attr('width', width);
        this.svg.attr('height', height);

        this.svg.select('path').attr('d', d3Path);

        return this.svg.node();
    }
}

class Maps {
    map = null;  // 地图对象
    mapList = []; // 地图底图种类
    selMapType = 1; // 当前底图种类 1影像 2街道 3地形
    olLayers = {};  // ol底图对象集合
    isPolymerization = false; // 是否点位聚合
    polygonLayer = {}; // 图形图层集合，以layerKey为下标

    /**
     * @name: mapInit
     * @desc: 初始化地图
     * @param {String} mapType 底图类型
     * @param {jsonString} mapBaseParam 底图图层json
     * @param {Object} mapInfo 地图基础信息
     * @param {String} target 地图容器id
     * @param {Boolean} isHaveShade 是否有遮罩
     * @param {Boolean} isPolymerization 是否点位聚合
     * @param {StringNumber} selMapType 地图种类
     */
    mapInit({mapType, mapBaseParam, mapInfo, target, isHaveShade = false, selMapType = 1, isPolymerization = false}) {
        this.isPolymerization = isPolymerization;
        if (mapType === 'OL4') {
            this.initOlMap(mapBaseParam, mapInfo, target, isHaveShade, selMapType);
        } else if (mapType === 'offline') {
            this.initGoogleMap(mapBaseParam, mapInfo, target, isHaveShade, selMapType);
        } else if (mapType === 'gaode') {
            // this.initAMap(mapBaseParam, mapInfo, target)
        }
        this.initClick();
    }

    /**
     * @name: getOlMap
     * @desc: 初始化ol地图
     * @param {Object} mapBaseParam 底图图层json
     * @param {Object} mapInfo 地图基础信息
     * @param {Object} target 地图容器id
     * @param {Boolean} isHaveShade 是否有遮罩
     * @param {StringNumber} selMapType 地图种类
     */
    initOlMap(mapBaseParam, mapInfo, target, isHaveShade, selMapType) {
        // 处理天地图的图层
        if (!mapBaseParam) return;
        let layerObj = {}; // 图层对象
        console.log(mapBaseParam);
        console.log(mapInfo);
        mapBaseParam.forEach((item) => {
            if (this.mapList.indexOf(item.name) === -1) {
                this.mapList.push(item.name);
            }
            layerObj[item.name] = layerObj[item.name] || [];
            layerObj[item.name].push(item);
        });
        // 初始化地图
        let projection = get('EPSG:4326');
        let projectionExtent = projection.getExtent();
        let size = getWidth(projectionExtent) / 256;
        let resolutions = [];
        for (let z = 0; z < 21; ++z) {
            resolutions[z] = size / Math.pow(2, z);
        }
        let matrixIds = []; //分辨率对应的数组,根据最大和最小的zoom去决定
        for (let i = mapInfo.mapMinZoom; i < mapInfo.mapMaxZoom + 1; i++) {
            matrixIds.push(i.toString());
        }
        let layers = [];
        // 图层
        for (let key in layerObj) {
            let objList = layerObj[key];
            let layer = [];
            for (let i = 0; i < objList.length; i++) {
                layer.push(new TileLayer({
                    source: new WMTSSource({
                        name: objList[i].name,
                        layerType: objList[i].layerType,
                        url: objList[i].url,
                        layer: objList[i].layer,
                        matrixSet: objList[i].matrixSet,
                        format: objList[i].format ? objList[i].format : 'image/png',
                        isBaseLayer: i == 0 ? true : false,
                        style: objList[i].style ? objList[i].style : 'default',
                        tileGrid: new WMTSTileGrid({
                            origin: getTopLeft(projectionExtent),
                            resolutions: resolutions.slice(mapInfo.mapMinZoom, mapInfo.mapMaxZoom + 1),
                            matrixIds,
                            tileSize: 256
                        })
                    }),
                    visible: false
                }));
            }
            this.olLayers[key] = layer;
            layers = layers.concat(this.olLayers[key]);
        }

        this.map = new Map({
            layers,
            target: target,
            view: new View({
                center: [+mapInfo.mapDefaultCenter.split(',')[0], +mapInfo.mapDefaultCenter.split(',')[1]],
                projection,
                zoom: mapInfo.mapDefaultZoom,
                maxZoom: mapInfo.mapMaxZoom,
                minZoom: mapInfo.mapMinZoom,
                resolutions
            })
        });
        this.switchMap(selMapType);
        // 绘制反向遮罩
        // if (isHaveShade) {
        //     this.addShadow()
        // }
    }

    /**
     * @name: switchMap
     * @desc: 切换地图
     * @param {Number} type 地图类型
     */
    switchMap(type) {
        // 若调用的时候地图类型相同，则不变化
        // if(type === this.selMapType) return
        let selMap = mapArr.find((obj) => {
            return +obj.mapType === +type;
        });
        this.mapList.forEach(key => {
            this.olLayers[key].forEach(layer => {
                if (selMap.key === key) {
                    layer.setVisible(true);
                } else {
                    layer.setVisible(false);
                }
            });
        });
        this.selMapType = type;
    }

    initClick() {
        // 点击出现详情弹窗
        this.map && this.map.on('singleclick', (e) => {
            console.log(e.coordinate);
        });
    }

    /**
     * @name: createPolygon
     * @desc: 绘制区域范围
     * @param {*} path
     * @param {*} style
     */
    createPolygon(path, style, data) {
        const feature = new Feature({
            geometry: new Polygon([path]),
            data: {
                type: data.type ?? 'polygon',
                ...data
            }
        });
        // 设置样式
        feature.setStyle(new Style({
            stroke: new Stroke({
                color: style.strokeColor ? style.strokeColor : '#333',
                width: style.strokeWeight ? style.strokeWeight : 2,
                lineDash: style.lineDash ? style.lineDash : undefined
            }),
            fill: new Fill({
                color: style.fillColor
            })
        }));
        console.log(feature.getGeometry());
        console.log(feature);
        return feature;
    }

    /**
     * @name: addPolygons
     * @desc: 图层是面的时候，添加面
     */
    addSvgPolygons({layerId, pointList}) {
        let polygonFeature = this.createPolygon(
            pointList,
            {
                strokeColor: '#5b8ff9',
                strokeWeight: 2,
                lineDash: undefined,
                fillColor: 'rgba(255, 143, 249, 0.2)'
            },
            {
                layerId: layerId
            }
        );
        this.polygonLayer[layerId] = new VectorLayer({
            source: new VectorSource({
                features: [polygonFeature]
            }),
            zIndex: 98
        });
        this.map.addLayer(this.polygonLayer[layerId]);

        // 添加svg区域
        const layer = new CanvasLayer({
            areaList: pointList
        });

        this.map.addLayer(layer);
    }
}

export default Maps;